In the field of computing, software typically exhibits modular characteristics rather than being monolithic. Moreover, there are oftentimes a number of separate and distinct algorithms employed within any given piece of software. Such disparate algorithms combine in such a manner so as to provide services (i.e., functionalities) that are needed by the software. It is often the case that for one particular service, many different algorithms are available. Generally speaking, an algorithm in this scenario is a sequence of computational steps that carries out a task or a set of tasks. An algorithm can have various sizes. It can be very large, or it can be as small as a set of a few instructions. An algorithm can contain smaller algorithms, which in turn can contain even smaller algorithms. This hierarchy may have any number of levels.
It is well understood that such software can be reverse engineered or otherwise tampered with by an attacker in many ways. Such tampering is undesirable in many commercial applications and has given rise to cryptography to counter any such attacks. This is particularly evident in large scale server-client applications. In such applications, frequent updates of client software for the purposes of deploying new features or to patch security vulnerabilities can lead to a whole new class of attacks requiring refined cryptography techniques. This is because updating software with new protection can have the unintended consequence of leading an attacker directly to the protected assets whereby the attacker needs only to compare to previous versions of the software.
Such additional attacks are not limited to differential attacks of software revisions for the identification of assets, but may also include collusion between parties which itself may lead to key sharing schemes, or may also include code-lifting attacks that might identify important modules such as code used to generate device keys or roots-of-trust. Code-lifting can lead to rogue systems where some of the real application is reused together with an attacker's code. In such instances, damage can spread very quickly, as exploits are often posted at various places on the Internet.
In the protection of software, layered defenses are often presented as a high entry barrier to a system. However, applying layered protection against such new class of attacks is often a trade-off between the performance and size of an application. Existing efforts to reduce the window of opportunity to exploit vulnerabilities exposed by this trade-off include relying upon the capability for build-time diversity.
One way to reduce the risk of differential attacks across several clients is to make individual differing instances of the software. In another situation, software can be upgraded (e.g., to support new features, enhance performance, or to patch vulnerabilities) using build-time diversity capability to renew the software as well as to distribute the new protection of the vulnerable module. This allows the full software revision to be diverse with respect to the former revision, preventing obvious differential attacks. In yet another situation, diversity can also play a part in enabling revocation schemes by creating a data diversity capability. This is a useful feature for disallowing clients to connect to a server if, for example, they do not comply with company policies (e.g. don't pay the bills). However, such diversity schemes encounter scaling problems in larger deployments due to the increased need for more and more differing programs which must all be constructed by build tools, which traditionally take a long time to execute.
Existing build-time techniques to produce diverse programs suffer from an inability to produce large-scale deployments of different instances in both an efficient manner and with a high confidence level. The difficulty in confidence level is manifested through the inability of known systems and methods to test a large set of diverse program instances. In particular, the time required for testing all diverse instances can be unfeasibly high if there are a large number of instances. An efficient method for generating diverse instances with regard to the ability to test would improve the cycle of deployment from both a build-time and validation perspective. It is, therefore, desirable to provide a more universally useful system and method to increase build-time diversity.